﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace net.veekee.common.reflection
{
    public class TypeList
    {
        private List<String> types = null;
        public List<String> Items
        {
            get
            {
                return this.types;
            }
        }

        public TypeList()
        {
            this.types = new List<String>();
        }

        private void AddTypes(Assembly a, String nsConstraint = null)
        {
            if (a == null)
                return;
            try
            {
                foreach (Type type in a.GetTypes())
                {
                    if (type.Namespace == null)
                        continue;
                    if (nsConstraint != null && !type.Namespace.Equals(nsConstraint))
                        continue;
                    if (!type.IsClass || type.IsAbstract)
                        continue;
                    Log.GetInstance().Debug("Adding class '" + type.FullName + "'");
                    this.types.Add(type.FullName);

                    Type interfac = type.GetInterface(typeof(ITypeListHandler).FullName);
                    if (interfac != null)
                    {
                        Log.GetInstance().Debug("Registering class '" + type.FullName + "'");
                        ITypeListHandler typehandler = ReflectionManager.CreateObject<ITypeListHandler>(type.FullName);
                        if (typehandler != null)
                            typehandler.OnRegister();
                    }
                }
            }
            catch
            {
                Log.GetInstance().Info("Assembly '{0}' does not support type enumeration", a.FullName);
            }
        }

        public void AddNamespace(String ns)
        {
            Log.GetInstance().Debug("Adding all classes from namespace '" + ns + "'");
            this.AddTypes(Assembly.GetCallingAssembly(), ns);
        }

        public void AddFolder(String folder, String pattern = "*.plugin")
        {
            Log.GetInstance().Debug("Adding all files from folder '" + folder + "'");
            System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(folder);
            if (!di.Exists)
            {
                Log.GetInstance().Debug("Folder '" + folder + "' doesn't exist !");
                return;
            }
            String[] files = System.IO.Directory.GetFiles(di.FullName, pattern, System.IO.SearchOption.AllDirectories);
            foreach (String file in files)
            {
                Log.GetInstance().Debug("Adding file '" + file + "'");
                Assembly a = ReflectionManager.AddAssemblyFromFile(file);
                this.AddTypes(a);
            }
        }

        public void FilterItems(String cls)
        {
            Log.GetInstance().Debug("Fitering items with '" + cls + "'");
            List<String> localTypeList = new List<String>();
            Type tcls = ReflectionManager.GetType(cls);
            foreach (String t in this.types)
            {
                Type tt = ReflectionManager.GetType(t);
                if (tt == null)
                    continue;
                if (!tt.IsClass || tt.IsAbstract)
                    continue;
                if (tt.IsSubclassOf(tcls))
                    localTypeList.Add(t);
            }
            this.types = localTypeList;
        }
    }
}
